from django import http
from django.views import View
from apps.users.models import User
import json
import re
from django_redis import get_redis_connection
from django.contrib.auth import login, authenticate, logout
from utility.views import LoginRequiredJsonMixin
from celery_tasks.email.tasks import send_email_info
from apps.users.utility import activateurl
from apps.oauth.utility import changepassword, restorepassword
from apps.users.models import Address
from apps.goods.models import SKU
from apps.carts.tools import merge_good_carts


# Create your views here.
# 判断用户名
class UsernameCountView(View):
    """
    判断前段请求的用户名是否在数据库中
    """

    def get(self, request, usernames):
        print(usernames)
        '''
        判断username在数据库对应的表格中出现的次数
        :param request:
        :return: 如果==1表示已存在，返回一个错误信息，==0表示数据不存在，返回对应的数据
        '''
        try:
            count = User.objects.filter(username=usernames).count()
        except Exception as e:
            return http.JsonResponse({'code': 400, 'errmsg': '格式错误'})

        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'count': count})


# 判断手机号
class MobileCountView(View):
    """
    判断手机号是否存在
    """

    def get(self, request, mobile):

        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            return http.JsonResponse({'code': '400', 'errmsg': '格式错误'})

        return http.JsonResponse({'code': '0', 'errmsg': 'ok', 'count': count})


# 注册
class RegisterView(View):
    """
    用于实现注册逻辑
    """

    def post(self, request):
        # 获取数据解析成json字典
        json_dict = json.loads(request.body.decode())

        print(json_dict)

        # 获取对应数据
        username = json_dict.get('username')
        # print(username)
        password = json_dict.get('password')
        password2 = json_dict.get('password')
        mobile = json_dict.get('mobile')
        sms_code = json_dict.get('sms_code')
        allow = json_dict.get('allow')

        # ==>判断数据：
        # 判断参数是否为空
        if not all([username, password, mobile, sms_code]):
            return http.JsonResponse({'code': '400', 'errmsg': '错误数据'})

        # 判断用户名格式
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.JsonResponse({'code': '400', 'errmsg': '用户名格式有误'})

        # 判断密码格式
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.JsonResponse({'code': '400', 'errmsg': '密码格式有误'})

        # 判断密码是否一致
        if password2 != password:
            return http.JsonResponse({'code': '400', 'errmsg': '密码不一致'})

        # 判断是否同意美多商城用户使用协议
        if not allow:
            return http.JsonResponse({'code': '400', 'errmsg': '需要同意美多商城用户使用协议'})

        # 判断短信验证码是否一致
        redit_conn = get_redis_connection('verify_code')
        # 根据手机号获取数据库的短信验证码sms_code
        sms_code_server = redit_conn.get('sms_code_ %s' % mobile)
        # 如果 not null
        if not sms_code_server:
            return http.JsonResponse({'code': '400', 'errmsg': '短信验证码已失效'})

        # 如果存在就比较请求数据里面的sms_code是否和数据库的相等
        if sms_code != sms_code_server.decode():
            return http.JsonResponse({'code': '400', 'errmsg': '短信验证码错误'})

        # ==>保存数据：
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except Exception as e:
            return http.JsonResponse({'code': '400', 'errmsg': '错误数据'})

        # 保持登录状态
        login(request, user)

        return http.JsonResponse({'code': '0', 'errmsg': 'ok'})


# 状态保持
class LoginView(View):
    """
    登录视图
    """

    def post(self, request):
        json_dict = json.loads(request.body.decode())
        username = json_dict.get('username')
        password = json_dict.get('password')
        remembered = json_dict.get('remembered')

        if not all([username, password]):
            return http.JsonResponse({'code': 400, 'errmsg': '信息不能为空'})

        if re.match(r'^1[3-9]\d{9}$', username):
            User.USERNAME_FIELD = 'mobile'
        else:
            User.USERNAME_FIELD = 'username'

        # authenticate是django封装好的来判断用户名和密码是否正确
        user = authenticate(request, username=username, password=password)

        if not user:
            return http.JsonResponse({'code': 400, 'errmsg': '用户名密码错误'})

        # 状态保持
        login(request, user)

        if remembered:
            request.session.set_expiry(None)
        else:
            request.session.set_expiry(0)

        response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username, max_age=None)

        # 合并购物车
        merge_good_carts(request, user, response)

        return response


# 退出当前用户
class LogoutView(View):
    """
    用于退出登录
    """

    # DELETE http: // www.meiduo.site: 8000 / logout /
    def delete(self, request):
        logout(request)

        response = http.JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.delete_cookie('username')

        return response


# 用户中心信息展示
class UserInfoView(LoginRequiredJsonMixin, View):
    """
    用于用户中心
    """

    def get(self, request):
        """
        实现用户信息展示
        :param request:
        :return:
        """
        data_dict = {
            'code': 0,
            'errmsg': 'OK',
            'info_data': {
                'username': request.user.username,
                'mobile': request.user.mobile,
                'email': request.user.email,
                'email_active': request.user.email_active
            }
        }
        return http.JsonResponse(data_dict)


# 用户中心-邮箱
class UserEmailView(View):
    """用户中心添加邮箱"""

    def put(self, request):
        json_dict = json.loads(request.body.decode())
        email_client = json_dict.get('email')

        if not all([email_client]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        if not re.match(r'^\w+[-_.]*[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$', email_client):
            return http.JsonResponse({'code': 400, 'errmsg': '邮箱格式有误'})

        # try:
        #     User.objects.get(email=email_client)
        # except DoesNotExist:
        #     return http.JsonResponse({'code': 400, 'error_message': '邮箱已被注册'})
        count = User.objects.filter(email=email_client).count()
        # print(count)
        # if count != 0:
        #     return http.JsonResponse({'code': 400, 'errmsg': '邮箱已被注册'})

        try:
            request.user.email = email_client
            request.user.save()
        except Exception as e:
            return http.JsonResponse({'code': 400, 'errmsg': '保存失败'})
        print('request.user.id===========', request.user.id)
        # print(email_client)
        activate_url = activateurl(user_id=request.user.id)
        # print(activate_url)
        try:
            send_email_info.delay(email_client, activate_url)
        except Exception as e:
            return http.JsonResponse({'code': 400, 'errmsg': '发送失败'})

        return http.JsonResponse({'code': 0, 'errmsg': 'ok'})


# 激活邮箱
class ActivateEmailView(View):
    """
    用于邮箱激活
    """

    def put(self, request):
        """
        实现邮箱激活
        :param request:
        :return:
        """
        token = request.GET.get('token')

        if not token:
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        user_id = restorepassword(token)
        # print(user_id)
        try:
            User.objects.filter(id=user_id).update(email_active=True)
        except Exception as e:

            return http.JsonResponse({'code': 400, 'errmsg': '激活失败'})

        return http.JsonResponse({'code': 0, 'errmsg': 'ok'})


# 修改用户密码
class UpdatePasswordView(LoginRequiredJsonMixin, View):
    """修改密码"""

    def put(self, request):
        json_dict = json.loads(request.body.decode())
        old_password = json_dict.get('old_password')
        new_password = json_dict.get('new_password')
        new_password2 = json_dict.get('new_password2')

        if not all([old_password, new_password, new_password2]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        if not re.match(r'^[a-zA-Z0-9]{8,20}$', new_password):
            return http.JsonResponse({'code': '400', 'errmsg': '密码格式有误'})

        if not request.user.check_password(old_password):
            return http.JsonResponse({'code': 400, 'errmsg': '当前密码错误'})
        if not new_password2 == new_password:
            return http.JsonResponse({'code': 400, 'errmsg': '两次密码不一致'})

        try:
            # 将新密码加密保存set_
            request.user.set_password(new_password)

            request.user.save()
        except Exception as e:
            return http.JsonResponse({'code': 400, 'errmsg': '密码修改失败，请重试'})

        logout(request)
        response = http.JsonResponse({'code': 0, 'errmsg': '密码修改成功'})
        response.set_cookie('username')
        return response


# 新增地址
class AddAddressView(LoginRequiredJsonMixin, View):
    """新增保存地址"""

    def post(self, request):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': '手机号格式错误'})

        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.JsonResponse({'code': 400, 'errmsg': '电话格式错误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.JsonResponse({'code': 400, 'errmsg': '邮箱格式错误'})

        user = Address.objects.create(
            user=request.user,
            title=receiver,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email
        )

        # 判断当前用户的默认地址是否为空，如果为空设置当前地址为默认地址
        if not request.user.default_address:
            request.user.default_address = user
            request.user.save()
        return http.JsonResponse({'code': 0, 'errmsg': '保存成功'})


# 删除地址和编辑地址
class UpdateAddressView(View):

    def delete(self, request, id):
        count = Address.objects.filter(id=id).count()
        if count == 0:
            return http.JsonResponse({'code': 400, 'ermsg': '信息不存在'})

        Address.objects.filter(id=id).update(is_deleted=True)
        return http.JsonResponse({'code': 0, 'ermsg': '删除成功'})

    def put(self, request, id):
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.JsonResponse({'code': 400, 'errmsg': '手机号格式不正确'})

        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.JsonResponse({'code': 400, 'errmsg': 'tel格式不正确'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.JsonResponse({'code': 400, 'errmsg': 'emmail格式不正确'})

        request.user.addresses.filter(id=id).update(
            id=id,
            receiver=receiver,
            province_id=province_id,
            city_id=city_id,
            district_id=district_id,
            place=place,
            mobile=mobile,
            tel=tel,
            email=email,

        )

        info_dict = {
            'id': id,
            'receiver': receiver,
            'province': request.user.addresses.get(id=id).province.name,
            'city': request.user.addresses.get(id=id).city.name,
            'district': request.user.addresses.get(id=id).district.name,
            'place': place,
            'mobile': mobile,
            'tel': tel,
            'email': email,
            'title': request.user.addresses.get(id=id).title
        }

        return http.JsonResponse({'code': 0, 'errmsg': '修改成功', 'address': info_dict})


# 显示收货地址
class UserAddressView(View):

    def get(self, request):
        addresses = request.user.addresses.filter(is_deleted=False)

        address_list = []

        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }
            address_list.append(address_dict)

        data = {
            'code': 0,
            'errmsg': 'ok',
            'default_address_id': request.user.default_address_id,
            "addresses": address_list,
        }

        return http.JsonResponse(data)


# 修改默认地址
class UpdateDefaultAdsView(View):

    def put(self, request, id):
        """
        实现修改默认地址
        :param request:
        :param id:
        :return:
        """

        try:
            request.user.default_address_id = id
            request.user.save()
        except Exception as e:

            return http.JsonResponse({'code': 400, 'errmsg': '修改失败，请重试'})

        return http.JsonResponse({'code': 0, 'errmsg': '修改成功'})


# 更改标题
class UpdateTitleView(View):
    def put(self, request, id):
        json_dict = json.loads(request.body.decode())
        title = json_dict.get('title')

        request.user.addresses.filter(id=id).update(title=title)

        return http.JsonResponse({'code': 0, 'errmsg': '修改成功'})


class UserBrowseView(LoginRequiredJsonMixin, View):
    # POST == > 请求地址browse_histories /== > 请求参数: sku_id(商品编号)
    # GET ==>用户中心浏览记录   /browse_histories/

    # 查看数据库显示浏览记录
    def get(self, request):
        redis_conn = get_redis_connection('user_browse')
        # LRANGE key start sto
        user_id = request.user.id
        key = 'record_%s' % user_id
        skus = redis_conn.lrange(key, 0, -1)
        skus_lsit = []
        for sku in skus:
            sku = int(sku)
            if not sku:
                return http.JsonResponse({'code': 400, 'errmsg': '数据错误'})
            sku_conn = SKU.objects.get(id=sku)
            skus_lsit.append({
                'id': sku_conn.id,
                'name': sku_conn.name,
                'default_image_url': sku_conn.default_image.url,
                'price': sku_conn.price
            })

        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'skus': skus_lsit})

    # 保存浏览记录到数据库
    def post(self, request):
        json_dick = json.loads(request.body.decode())
        sku_id = json_dick.get('sku_id')

        if not all([sku_id]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须商品编号'})
        # 建立redis数据库链接
        redis_conn = get_redis_connection('user_browse')
        pls = redis_conn.pipeline()
        user_id = request.user.id
        key = 'record_%s' % user_id
        pls.lrem(key, 0, sku_id)
        pls.lpush(key, sku_id)
        pls.ltrim(key, 0, 4)
        pls.execute()

        return http.JsonResponse({'code': 0, 'errmsg': 'ok'})
